/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.oimwrapper.testers;

import org.oimwrapper.testers.models.JSONRequest;
import Thor.API.Operations.tcFormDefinitionOperationsIntf;
import Thor.API.Operations.tcFormInstanceOperationsIntf;
import Thor.API.Operations.tcObjectOperationsIntf;
import Thor.API.tcResultSet;
import com.thortech.util.logging.Logger;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import org.apache.commons.beanutils.BeanUtils;
import org.junit.Test;
import org.oimwrapper.connectors.OIMAdapterBase;
import org.oimwrapper.connectors.OIMFormData;
import org.oimwrapper.connectors.OIMRemoteClientBase;
import org.oimwrapper.connectors.OIMRequest;
import org.oimwrapper.connectors.internal.OIMObjectFormUtilities;
import org.oimwrapper.connectors.internal.OIMUtilityGetter;
import org.oimwrapper.testers.models.*;

/**
 *
 */
public class ClientGenericRequestTester extends ClientBaseTester {
    
    
    private static final Logger logger = Logger.getLogger(ClientGenericRequestTester.class.getName());
    //private static final String childRoleTableName = "Lookup.ChildRoleTableName";

    private static OIMAdapterBase apiBase;
    private OIMRemoteClientBase tester;
    
    private tcFormInstanceOperationsIntf formInstOps;
    private tcFormDefinitionOperationsIntf formDefOps;
    private tcObjectOperationsIntf objectOp;
    private OIMObjectFormUtilities objFormUtils;
    
    @Test
    public void mainTest()
    {
        try {
            tester = this.connect();
            apiBase = tester.getUtils();
            formInstOps = (tcFormInstanceOperationsIntf)apiBase.getUtility(Thor.API.Operations.tcFormInstanceOperationsIntf.class);
            formDefOps = (tcFormDefinitionOperationsIntf)apiBase.getUtility(Thor.API.Operations.tcFormDefinitionOperationsIntf.class);
            objectOp = (tcObjectOperationsIntf)apiBase.getUtility(Thor.API.Operations.tcObjectOperationsIntf.class);
            objFormUtils = OIMUtilityGetter.getObjectFormUtilities(logger, objectOp,formInstOps, formDefOps);
        } catch (Exception ex) {
            logger.error("Exception",ex);
            return;
        }
        
        //getObjectForm();
        try
        {
            RequestBean rb = mapJSONRequest(JSONRequest.CREATE_RESOURCE_C_GROUP);
            logger.debug("Request Bean From JSON");
            logger.debug("" + rb);
            createRequest(rb);
        }
        catch(Exception e)
        {
            logger.error("Error",e);
        }
        
    }
    
    /*
     * this code will translate a field from its display name to the DB field name of the corresponding field in the
     * UD table.
     */
    private RequestBean mapJSONRequest(String jsonString) throws Exception
    {
        logger.debug("mapJSON");
        
        JDBCHandler jdbcHandler = null;
        try
        {
            jdbcHandler = new JDBCHandler();
        }
        catch(Exception e)
        {
            logger.error("DBFailed",e);
            throw e;
        }
        
        JSONRequest jsonRequest = new JSONRequest();
        RequestBean rb = jsonRequest.getRequestFromJSON(jsonString);
        logger.debug("RB:" + rb);
        String resourceName = rb.getUD_GRES_O_RESOURCENAME();
        String requestType = rb.getUD_GRES_O_REQUESTTYPE();
        
        List<OIMField> fields = jdbcHandler.getOimFieldMaps(rb.getUD_GRES_O_RESOURCENAME(), rb.getUD_GRES_O_REQUESTTYPE());
        
        if (fields == null || fields.isEmpty())
        {
            throw new Exception("Field Definition Not Found");
            
        }
        List<RequestParentBean> rpbs = rb.getPARENTDATA();
        List<RequestChildBean> rcbs = rb.getCHILDDATA();
        
        for(RequestParentBean rpb : rpbs)
        {
            logger.debug("Parent:" + rpb);
            String name = rpb.getUD_GRES_OA_NAME();
            OIMField fld = new OIMField();
            fld.setRequestType(requestType);
            fld.setResourceName(resourceName);
            fld.setFieldLabel(name);
            
            int index = fields.indexOf(fld);
            if (index >= 0)
            {
                logger.debug("GOT IT!");
                OIMField thisFld = fields.get(index);
                logger.debug("" + thisFld);
                rpb.setUD_GRES_OA_NAME(thisFld.getColumnName());
            }
            
        }
        
        for(RequestChildBean rcb : rcbs)
        {
            logger.debug("Child:" + rcb);
            String name = rcb.getUD_GRES_OC_NAME();
            OIMField fld = new OIMField();
            fld.setRequestType(requestType);
            fld.setResourceName(resourceName);
            fld.setFieldLabel(name);
            int index = fields.indexOf(fld);
            if (index >= 0)
            {
                logger.debug("GOT IT!");
                OIMField thisFld = fields.get(index);
                logger.debug("" + thisFld);
                rcb.setUD_GRES_OC_NAME(thisFld.getColumnName());
                rb.setUD_GRES_O_ROLE_TABLENAME(thisFld.getChildTableName());
            }
            
        }
        
        return rb;
    }
    
    /*
     * 
     */
    public void createRequest(RequestBean requestBean)
    {
        Map requestData = null;
        List<RequestParentBean> rpbs = null;
        List<RequestChildBean> rcbs = null;
        
        try
        {
            requestData = BeanUtils.describe(requestBean);
            rpbs = requestBean.getPARENTDATA();
            rcbs = requestBean.getCHILDDATA();
        }
        catch(Exception e)
        {
            logger.error("BeanConversionError",e);
            return;
        }
        
        try
        {
            OIMFormData form = new OIMFormData();
            OIMRequest oimRequest = new OIMRequest(OIMRequest.RequestForOrg);
            String requesterId = (String)requestData.get("UD_GRES_O_REQUESTER");
            String requesterKeyStr = apiBase.getOimUserAttribute(requesterId, "Users.Key");

            if (requesterKeyStr == null)
            {
                logger.error("Failed to get User " + requesterId);
                return;
            }

            
            form.setParentData(requestData);

            
            ArrayList childDataMapList = new ArrayList();

            for(RequestParentBean rp : rpbs)
            {
                Map childData = new HashMap();
                childData.put("UD_GRES_OA_NAME",rp.getUD_GRES_OA_NAME());
                childData.put("UD_GRES_OA_VALUE", rp.getUD_GRES_OA_VALUE());
                childDataMapList.add(childData);
            }
            
            if (!childDataMapList.isEmpty())
                form.setChildData("UD_GRES_OA", (Map[])childDataMapList.toArray(new Map[0]));
            
            ArrayList childDataMapList2 = new ArrayList();
            
            int seqnum = 0;
            for(RequestChildBean rc : rcbs)
            {
                Map childData2 = new HashMap();
                childData2.put("UD_GRES_OC_NAME",rc.getUD_GRES_OC_NAME());
                childData2.put("UD_GRES_OC_VALUE",rc.getUD_GRES_OC_VALUE());
                childData2.put("UD_GRES_OC_SEQNUM",rc.getUD_GRES_OC_SEQNUM());
                childDataMapList2.add(childData2);
            }
            
            if (!childDataMapList2.isEmpty())
                form.setChildData("UD_GRES_OC", (Map[])childDataMapList2.toArray(new Map[0]));
            
            oimRequest.addResourceObject(apiBase.getResourceObject("Generic Resource Request"), form);
            
            long orgKey = apiBase.getOrganization("Requests");
            oimRequest.addTargetOrg(orgKey);
            long reqKey = apiBase.createRequest(oimRequest, orgKey);
            Map newRequestData = apiBase.getRequest(reqKey);
            logger.debug("Request Created " + reqKey);

        }
        catch(Exception ex)
        {
            logger.error("Exception",ex);
        }
        
    }
    
    private List getUsers(String userSrch)
    {
        List userList = new ArrayList();
        try
        {
            Map srchFor = new HashMap();
            srchFor.put("Users.User ID",userSrch);
            Map[] users = apiBase.getOimUsersData(srchFor);
            for(int i=0;i<users.length;i++)
            {
                Map m = users[i];
                String u = (String)m.get("Users.User ID");
                userList.add(u);
            }
        }
        catch(Exception e)
        {
            logger.error("APIError",e);
        }
        return userList;
    }
    
}
